package com.gitee.wsl.collections.map

import com.gitee.wsl.collections.bean.SampleMapEntry
import com.gitee.wsl.ext.collection.getByIndex
import com.gitee.wsl.ext.list.getByIndexes
import com.gitee.wsl.func.BiFunction
import com.gitee.wsl.func.consumer.BiConsumer
import kotlin.jvm.JvmOverloads


/**
 * 可重复键和值的Map<br></br>
 * 通过键值单独建立List方式，使键值对一一对应，实现正向和反向两种查找<br></br>
 * 无论是正向还是反向，都是遍历列表查找过程，相比标准的HashMap要慢，数据越多越慢
 *
 * @param <K> 键类型
 * @param <V> 值类型
 * @author looly
</V></K> */
class TableMap<K, V> : Map<K, V>{
    
    val keysList: MutableList<K>
    
    override val values: MutableList<V>

    override val keys: Set<K>
        get() = keysList.toSet()
    
    /**
     * 构造
     *
     * @param size 初始容量
     */
    /**
     * 构造
     */
    @JvmOverloads
    constructor(size: Int = DEFAULT_CAPACITY) {
        this.keysList = ArrayList(size)
        this.values = ArrayList(size)
    }

    /**
     * 构造
     *
     * @param keys   键列表
     * @param values 值列表
     */
    constructor(keys: Array<K>, values: Array<V>) {
        this.keysList = keys.toMutableList()
        this.values = values.toMutableList()
    }

    override val size: Int
        get() = keysList.size
    
    
     override fun isEmpty(): Boolean {
        return keysList.isEmpty()
    }

    override fun containsKey(key: K): Boolean {
        return keysList.contains(key)
    }

     override fun containsValue(value: V): Boolean {
        return values.contains(value)
    }

     override fun get(key: K): V? {
        val index = keysList.indexOf(key)
        if (index > -1) {
            return values[index]
        }
        return null
    }

    /**
     * 根据value获得对应的key，只返回找到的第一个value对应的key值
     *
     * @param value 值
     * @return 键
     * @since 5.3.3
     */
    fun getKey(value: V): K? {
        val index = values.indexOf(value)
        if (index > -1) {
            return keysList.getByIndex(index)
        }
        return null
    }

    /**
     * 获取指定key对应的所有值
     *
     * @param key 键
     * @return 值列表
     * @since 5.2.5
     */
    fun getValues(key: K): List<V> {
        val keyIndexes:List<Int> = keysList.foldIndexed(mutableListOf<Int>()){index,list,value->
            if(value == key)
                list.add(index)
            list
        }
        return values.getByIndexes(keyIndexes)
    }

    /**
     * 获取指定value对应的所有key
     *
     * @param value 值
     * @return 值列表
     * @since 5.2.5
     */
    fun getKeys(value: V): List<K> {
        val keyIndexes:List<Int> = values.foldIndexed(mutableListOf<Int>()){index,list,v->
            if(value == v)
                list.add(index)
            list
        }
        return keysList.getByIndexes(keyIndexes)
    }

    fun put(key: K, value: V) {
        keysList.add(key)
        values.add(value)
        //return null
    }

    /**
     * 移除指定的所有键和对应的所有值
     *
     * @param key 键
     * @return 最后一个移除的值
     */
    fun remove(key: K): V? {
        var lastValue: V? = null
        var index: Int
        while ((keysList.indexOf(key).also { index = it }) > -1) {
            lastValue = removeByIndex(index)
        }
        return lastValue
    }

    /**
     * 移除指定位置的键值对
     *
     * @param index 位置，不能越界
     * @return 移除的值
     */
    fun removeByIndex(index: Int): V? {
        keysList.removeAt(index)
        return values.removeAt(index)
    }

//    fun putAll(m: Map< K,  V>) {
//        for (entry in m.entries) {
//            this.put(entry.key, entry.value)
//        }
//    }

    fun clear() {
        keysList.clear()
        values.clear()
    }


    /**
     * 获取所有键，可重复，不可修改
     *
     * @return 键列表
     * @since 5.8.0
     */
//    fun keys(): List<K?> {
//        return Collections.unmodifiableList(this.keys)
//    }
//
//     override fun values(): Collection<V?> {
//        return Collections.unmodifiableList(this.values)
//    }

    override val entries: Set<Map.Entry<K, V>>
        get() {
            val hashSet = LinkedHashSet<Map.Entry<K, V>>()
            for (i in 0..<size) {
                hashSet.add(SampleMapEntry(keysList[i], values[i]))
            }
            return hashSet
        }
    

     /*fun iterator(): Iterator<Map.Entry<K, V>> {
        return object : Iterator<Map.Entry<K, V>>() {
            private val keysIter: Iterator<K> = keysList.iterator()
            private val valuesIter: Iterator<V?> = values.iterator()

             override fun hasNext(): Boolean {
                return keysIter.hasNext() && valuesIter.hasNext()
            }

             override fun next(): Map.Entry<K?, V?> {
                return MapUtil.entry(keysIter.next(), valuesIter.next())
            }

             override fun remove() {
                keysIter.remove()
                valuesIter.remove()
            }
        }
    }*/

    override fun toString(): String {
        return "TableMap{" +
                "keys=" + keys +
                ", values=" + values +
                '}'
    }

    fun forEach(action: BiConsumer<in K, in V>) {
        for (i in 0..<size) {
            action.accept(keysList[i], values[i])
        }
    }

    fun remove(key: K, value: V): Boolean {
        var removed = false
        var i = 0
        while (i < size) {
            if (key== keysList[i] && value == values[i]) {
                removeByIndex(i)
                removed = true
                // 移除当前元素，下个元素前移
                i--
            }
            i++
        }
        return removed
    }

    fun replaceAll(function: BiFunction<in K, in V, out V>) {
        for (i in 0..<size) {
            val newValue = function.apply(keysList[i], values[i])
            values[i] = newValue
        }
    }

    fun replace(key: K, oldValue: V, newValue: V): Boolean {
        for (i in 0..<size) {
            if ( key == keysList[i] && oldValue == values[i]) {
                values[i] = newValue
                return true
            }
        }
        return false
    }

    /**
     * 替换指定key的所有值为指定值
     *
     * @param key   指定的key
     * @param value 替换的值
     * @return 最后替换的值
     */
    fun replace(key: K, value: V): V? {
        var lastValue: V? = null
        for (i in 0..<size) {
            if (key == keysList[i]) {
                lastValue = values.set(i, value)
            }
        }
        return lastValue
    }

    fun computeIfPresent(key: K, remappingFunction: BiFunction<in K, in V, out V>): V? {
        var lastValue: V? = null
        var i = 0
        while (i < size) {
            if (key == keysList[i]) {
                val newValue: V? = remappingFunction.apply(key, values[i])
                if (null != newValue) {
                    lastValue = values.set(i, newValue)
                } else {
                    removeByIndex(i)
                    // 移除当前元素，下个元素前移
                    i--
                }
            }
            i++
        }
        return lastValue
    }

    companion object {
        private const val DEFAULT_CAPACITY = 10
    }
}
